Go grpc
Table of Contents
安装
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
# 添加环境变量 GOPATH
$ export PATH="$PATH:$(go env GOPATH)/bin"
$ echo $PATH | xargs -d ':' -n1 |grep go
> /usr/local/go/bin
# 确认已安装
$ protoc --version
> libprotoc 3.20.3
$ protoc-gen-go --version
> protoc-gen-go v1.28.1
$ protoc-gen-go-grpc --version
> protoc-gen-go-grpc 1.2.0
介绍
grpc 是一个高性能、开源和通用的 RPC 框架,由 Google 团队开发,用于在分布式系统中进行 RPC 调用 使用 hello.proto 生成服务端和客户端代码
syntax = "proto3";
// 客户端指定 client/pb 作为包名
option go_package = "server/pb";
package pb;
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
service Hello {
rpc SayHello(HelloRequest) returns (HelloResponse) {}
}
server
├── go.mod
├── go.sum
├── main.go
└── pb
├── hello.pb.go
├── hello.proto
└── hello_grpc.pb.go
client
├── go.mod
├── go.sum
├── main.go
└── pb
├── hello.pb.go
├── hello.proto
└── hello_grpc.pb.go
# 在服务端和客户端项目根目录执行命令, 按 protoc 生成源码
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
pb/hello.proto
服务端代码 server/main.go
服务端安装 grpc 库 go get google.golang.org/grpc@latest
初始化服务端代码 go mod init server
package main
import (
"fmt"
"context"
"net"
"google.golang.org/grpc"
// 引入 pb(protoc 生成的源码)
"server/pb"
)
// pb 的方法名称与 proto 文件中定义的 rpc 相关
type server struct {
pb.UnimplementedHelloServer
}
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
fmt.Println("Received: ", in.GetName())
return &pb.HelloResponse{Message: "Hello " + in.GetName()}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
fmt.Println("failed to listen: ", err)
}
s := grpc.NewServer()
pb.RegisterHelloServer(s, &server{})
fmt.Println("server listening at ", lis.Addr())
if err := s.Serve(lis); err != nil {
fmt.Println("failed to serve: ", err)
}
}
package main
import (
"context"
"flag"
"log"
"time"
"grpc_client/pb"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
const (
defaultName = "world"
)
var (
// 50051 是服务端监听的端口
addr = flag.String("addr", "127.0.0.1:50051", "the address to connect to")
name = flag.String("name", defaultName, "Name to greet")
)
func main() {
flag.Parse()
// 连接到server端,此处禁用安全传输
conn, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewHelloClient(conn)
// 执行RPC调用并打印收到的响应数据
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
}
# 编译服务端和客户端代码
go build
./server
./client
> 2024/04/06 19:12:17 Greeting: Hello world